import cssText from './index.jcss'
import ActionBar from './action.plugin.js'
import Plugin from '../plugin'
import {CN,EN,Web,Cst} from '../../config'

export const GridCfg = {
	ctxCfg:{
		lineWidth:1,
		fillStyle:Web.theme,
		strokeStyle:"#32353F",
		fontSize:20,
		imageSmoothingEnabled : true,
		globalAlpha:0.5
	},
	span:Web.ratio*2,
	div:20 
}
export default class Grid extends Plugin{
	constructor(...args){
		super(...args)

		this.name="Grid"
		this.grid = false
		this.actionBar = new ActionBar(this.$event)

		this.createClassName({
			grid:"grid"
		})
		this.injectStyle(cssText,this.cn)
		this.createLayer(this.cn.grid,EN.prerender)
		let {width,height} = document.pageRect()

		this.translate = {
			tx:width,
			ty:height
		}
		this.scale = 1
		this.render()
		this.bind()
		setTimeout(()=>{
			this.actionBar.$actionDom.querySelector(".geo-icon-grid").click()
		},50)
	}
	render(){
		let {$event} = this
		this.$layer.innerHTML="<canvas></canvas>"
		this.cvs = this.$layer.firstElementChild;
		this.updateCvs(document.pageRect())
		this.ctx = this.cvs.getContext("2d")
		Reflect.defineProperty(this.ctx,"fontSize",{
			set(v){
				this.font = this.font.replace(/\d+(?=px)/,v)
				this.pfs = v
			},
			get(){
				return this.pfs||24
			}
		})
	}
	updateCvs(rect){
		let {width,height} = rect
		this.cvs.merge({
			width : width*2,
			height : height*2
		})
	}
	bind(){
		this.actionBar.on("onToggleGrid",this.onToggleGrid.bind(this))
		this.$event.on(EN.theme,this.onThemeChange.bind(this))
		this.$event.on(EN.translate,this.onTranslate.bind(this))
		this.$event.on(EN.scale,this.onScale.bind(this))

		this.$event.on(EN.resize,(rect)=>{
			if(!this.grid)return;
			this.updateCvs(document.pageRect())
			this.draw()
		})
		this.$event.on(EN.leftPanel,(e)=>{
			this.$layer.classList[e?"add":"remove"](CN.slideRight)
			if(e){
				let btn = this.actionBar.actionBtns.onToggleGrid
				btn.classList.contains(CN.active)||btn.click()
			}
		})
	}
	onToggleGrid(data){
		this.$layer.classList[data.isActive?"add":"remove"](CN.show)
		this.$env.set("grid_active",data.isActive)
		this.grid = data.isActive
		data.isActive&&this.draw()
	}
	onTranslate(t){
		let {tx,ty} = t;
		this.translate = {
			tx:tx*2,
			ty:ty*2
		}
		if(this.grid)
			this.draw()
	}
	onScale(r){
		this.scale = r
		if(this.grid)
			this.draw()
	}
	onThemeChange(data){
		let ss = "#000000"
		if(data.fbg)
			ss=(data.fbg==="transparent"||data.fbg==="#FFFFFF"||data.fbg==="#FFFFEE")?"#000000":data.f
		GridCfg.ctxCfg.merge({
			fillStyle:data.bg,
			strokeStyle:ss
		})
		if(!this.grid)return
		this.draw()
	}
	draw(){
		let {cvs,translate,scale} = this
		let {width,height} = document.pageRect()
		let {ctxCfg,span,div} = GridCfg
		let ctx =cvs.getContext("2d")
		let {tx,ty} = translate
		
		ctx.clearRect(0,0,width*2,height*2)

		ctx.save()
		//-0.5 的目的修复线条模糊 粗细不一
		ctx.translate(tx-0.5,ty-0.5)

		ctx.merge(ctxCfg)
		//draw grid line
		let mw = Math.max(tx,width*2-tx)
		let mh = Math.max(ty,height*2-ty)

		this.drawGridLine(ctx,{
			mw,mh,
			span:div,
			strokeStyle:ctxCfg.strokeStyle+"22"
		})

		this.drawGridLine(ctx,{
			mw,mh,span,
			strokeStyle:ctxCfg.strokeStyle+"88"
		})

			ctx.save()

			ctx.globalAlpha = 1
			this.drawRule(ctx,{mw,mh,span})
			
			this.drawAxis(ctx,{mw,mh})

			ctx.restore()

		this.drawCenter(ctx,ctxCfg.strokeStyle)

		ctx.restore()
	}
	drawGridLine(ctx,args){
		let {mw,mh,span,strokeStyle} = args
		ctx.save()
		ctx.strokeStyle = strokeStyle
		for(let i=0;i<mw;i+=span){
			this.drawLine([{x:i,y:-mh},{x:i,y:mh}],ctx)
			this.drawLine([{x:-i,y:-mh},{x:-i,y:mh}],ctx)
		}
		
		for(let i=0;i<mh;i+=span){
			this.drawLine([{x:-mw,y:i},{x:mw,y:i}],ctx)
			this.drawLine([{x:-mw,y:-i},{x:mw,y:-i}],ctx)
		}
		ctx.restore()
	}
	drawRule(ctx,args){
		let {mw,mh,span} = args
		let scale = this.scale
		for(let i=span;i<mw;i+=span){
			let m = this.fmt((i/span)/scale,scale)
			this.drawText([m,i,30],[`-${m}`,-i,30],ctx,"center")
		}
		for(let i=span;i<mh;i+=span){
			let m = this.fmt((i/span)/scale,scale)
			this.drawText([`-${m}`,-10,i+10],[m,-10,-i+10],ctx,"right")
		}
	}
	drawAxis(ctx,args){
		let {mw,mh} = args
		//x axios
		ctx.save()
		ctx.shadowBlur=5
		ctx.shadowColor=ctx.strokeStyle
		this.drawLine([{x:0,y:-mh},{x:0,y:mh}],ctx)
		//y axios
		this.drawLine([{x:-mw,y:0},{x:mw,y:0}],ctx)
		ctx.restore()
	}
	drawCenter(ctx,strokeStyle){
		ctx.save()
		ctx.strokeStyle = strokeStyle
		ctx.beginPath()
		ctx.arc(
			0,
			0,
			5,
			0,
			2*Math.PI)
		ctx.fill()
		ctx.stroke()
		ctx.restore()
	}
	drawText(a,b,ctx,textAlign){
		ctx.save()
		ctx.fillStyle = ctx.strokeStyle
		ctx.textAlign = textAlign
		ctx.fillText(a[0],a[1],a[2])
		ctx.strokeText(a[0],a[1],a[2])

		ctx.fillText(b[0],b[1],b[2])
		ctx.strokeText(b[0],b[1],b[2])
		ctx.restore()
	}
	drawLine(step,ctx){
		let fp=step[0]
		let sp=step[1]
		ctx.beginPath()
		ctx.moveTo(fp.x,fp.y)
		ctx.lineTo(sp.x,sp.y)
		ctx.closePath()
		ctx.stroke()
	}
	toFixed(scale){
		let flag = 1/scale
		if(flag>=1)return 0
		let r=(flag+"").match(/\.(0+)/)
		if(r)
			return r[1].length+2
		else
			return 2
	}
	fmt(n,scale){
		let pre = this.toFixed(scale)
		if(scale>1000||n<=0.001)
			return n.toExponential(2)
		if(scale<0.001||n>9999)
			return n.toExponential(2)
		return n.toFixed(pre)
	}	
}